﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EffiProz.Core.Store;

namespace EffiProz.Core.Lib
{
    public class MultiValueHashMap : BaseHashMap
    {
        protected Set _keySet;
        protected Collection _values;
        protected Iterator valueIterator;

        public MultiValueHashMap()
            : this(8)
        {

        }

        public MultiValueHashMap(int initialCapacity)
            : base(initialCapacity, BaseHashMap.objectKeyOrValue,
                BaseHashMap.objectKeyOrValue, false)
        {
            base.multiValueTable = new bool[base.objectValueTable.Length];
        }

        public Iterator get(Object key)
        {

            int hash = key.GetHashCode();

            return getValuesIterator(key, hash);
        }

        public Object put(Object key, Object value)
        {
            return base.addOrRemoveMultiVal(0, 0, key, value, false, false);
        }

        public Object remove(Object key)
        {
            return base.addOrRemoveMultiVal(0, 0, key, null, true, false);
        }

        public Object remove(Object key, Object value)
        {
            return base.addOrRemoveMultiVal(0, 0, key, value, false, true);
        }

        public override bool containsKey(Object key)
        {
            return base.containsKey(key);
        }

        public override bool containsValue(Object value)
        {
            return base.containsValue(value);
        }

        public void putAll(HashMap t)
        {

            Iterator it = t._keySet.iterator();

            while (it.hasNext())
            {
                Object key = it.next();

                put(key, t.get(key));
            }
        }

        public Set keySet()
        {

            if (_keySet == null)
            {
                _keySet = new KeySet(this);
            }

            return _keySet;
        }

        public Collection values()
        {

            if (_values == null)
            {
                _values = new Values(this);
            }

            return _values;
        }

        class KeySet : Set
        {

            private MultiValueHashMap _o;

            public KeySet(MultiValueHashMap _o)
            {
                this._o = _o;
            }

            public Iterator iterator()
            {
                return new MultiValueKeyIterator(_o);
            }

            public int size()
            {
                return _o.size();
            }

            public bool contains(Object o)
            {
                return _o.containsKey(o);
            }

            public Object get(Object key)
            {
                throw new Exception();
            }

            public bool add(Object value)
            {
                throw new Exception();
            }

            public bool addAll(Collection c)
            {
                throw new Exception();
            }

            public bool remove(Object o)
            {

                int oldSize = size();

                _o.remove(o);

                return size() != oldSize;
            }

            public bool isEmpty()
            {
                return size() == 0;
            }

            public void clear()
            {
                _o.clear();
            }
        }

        class Values : Collection
        {

            private MultiValueHashMap _o;

            public Values(MultiValueHashMap _o)
            {
                this._o = _o;
            }

            public Iterator iterator()
            {
                return new BaseHashIterator(_o, false);
            }

            public int size()
            {
                return _o.size();
            }

            public bool contains(Object o)
            {
                throw new Exception();
            }

            public bool add(Object value)
            {
                throw new Exception();
            }

            public bool addAll(Collection c)
            {
                throw new Exception();
            }

            public bool remove(Object o)
            {
                throw new Exception();
            }

            public bool isEmpty()
            {
                return size() == 0;
            }

            public void clear()
            {
                _o.clear();
            }
        }
    }
}
